var VSHADER_SOURCE = 'attribute vec2 a_TexCoord;\n' +  //纹理图片坐标
    'attribute vec4 a_Position;\n' +


    'attribute vec4 a_Color;\n' +   //物体颜色
    'attribute vec4 a_Normal;\n' +  //法向量

    'uniform mat4 u_MvpMatrix;\n' +      //模型视图投影矩阵
    'uniform mat4 u_ModelMatrix;\n' +    // 模型矩阵
    'uniform mat4 u_NormalMatrix;\n' +   // 法向量变换矩阵
    'attribute float a_ColorOrTex;\n' +  //图片（0）/纹理（1）
    'varying vec4 v_Color;\n' +
    'varying vec3 v_Normal;\n' +
    'varying vec3 v_Position;\n' +
    'varying vec2 v_TexCoord;\n' +     //纹理图片坐标
    'varying float v_ColorOrTex;\n' +  //图片（0）/纹理（1）
    'void main() {\n' +
    '  gl_Position = u_MvpMatrix * a_Position;\n' +
    // 计算世界坐标下的定点坐标
    '  v_Position = vec3(u_ModelMatrix * a_Position);\n' +
    '  v_Normal = normalize(vec3(u_NormalMatrix * a_Normal));\n' +
    '  v_Color = a_Color;\n' +
    '  v_TexCoord = a_TexCoord;\n' +
    '  v_ColorOrTex = a_ColorOrTex;\n' +
    '}\n';

// Fragment shader program
var FSHADER_SOURCE = '#ifdef GL_ES\n' +
    'precision mediump float;\n' +
    '#endif\n' +
    'uniform vec3 u_LightColor;\n' +     // 光照颜色
    'uniform vec3 u_LightPosition;\n' +  // 光的位置
    'uniform vec3 u_AmbientLight;\n' +   // 环境光的颜色
    'varying vec3 v_Normal;\n' +
    'varying vec3 v_Position;\n' +
    'varying vec4 v_Color;\n' +
    'varying vec2 v_TexCoord;\n' +     //纹理图片坐标
    'varying float v_ColorOrTex;\n' +  //图片（0）/纹理（1）
    'uniform sampler2D u_Sampler;\n' +
    'void main() {\n' +
    'vec4 color;\n' +
    'if(v_ColorOrTex == 1.0){\n' +
    `color = texture2D(u_Sampler, v_TexCoord);\n` +
    '}else{\n' +
    `color = v_Color;\n` +
    // 'color = v_Color;\n' +
    '}\n' +
    // 对法线进行归一化
    '  vec3 normal = normalize(v_Normal);\n' +
    // 计算光线方向并归一化
    '  vec3 lightDirection = normalize(u_LightPosition - v_Position);\n' +
    // 计算光线方向和法向量的点积
    '  float nDotL = max(dot(lightDirection, normal), 0.0);\n' +
    // 计算光照效果和环境光照效果
    '  vec3 diffuse = u_LightColor * color.rgb * nDotL;\n' +
    '  vec3 ambient = u_AmbientLight * color.rgb;\n' +
    //计算最终光照效果
    '  gl_FragColor = vec4(diffuse + ambient, color.a);\n' +
    '}\n';

// var VSHADER_SOURCE =
//     'attribute vec4 a_Position;\n' +
//     'attribute vec4 a_Color;\n' +
//     'uniform mat4 u_MvpMatrix;\n' +
//     'varying vec4 v_Color;\n' +
//     'void main() {\n' +
//     '  gl_Position = u_MvpMatrix * a_Position;\n' +
//     '  v_Color = a_Color;\n' +
//     '}\n';
//
// // Fragment shader program
// var FSHADER_SOURCE =
//     '#ifdef GL_ES\n' +
//     'precision mediump float;\n' +
//     '#endif\n' +
//     'varying vec4 v_Color;\n' +
//     'void main() {\n' +
//     '  gl_FragColor = v_Color;\n' +
//     '}\n';

function main() {
  var canvas = document.getElementById('cylinder');

  var gl = WebGLUtils.setupWebGL(canvas);
  if (!gl) {
    console.log('Failed to get the rendering context for WebGL');
    return;
  }


  gl.clearColor(0.0, 0.0, 0.0, 0.0);
  gl.enable(gl.DEPTH_TEST);
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

  drawCylinder(
      [0.0, 1.0, 0.0, 1.0], [0.0, -1.0, 0.0, 1.0], 1, [1.0, 0.0, 0.0], gl);
  // gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

  //   drawCylinder(
  //       [2.0, 0.0, 0.0, 1.0], [3.0, 0.0, 0.0, 1.0], 0.5, [1.0, 0.0, 0.0],
  //       gl);
  //   updateCylinder([1.0, 1.0, 0.0, 1.0], [1.0, -1.0, 0.0, 1.0], gl);
}

var n;

function drawCylinder(vertice1, vertice2, r, colors, gl) {
  if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
    console.log('Failed to intialize shaders.');
    return;
  }

  //圆柱的上下两点的向量
  var vector2_1 = new Array(3);
  //从原点到圆柱中心的向量 = 上下圆心的中点坐标
  var vector0_c = new Array(3);

  for (var i = 0; i < vector2_1.length; i++) {
    vector2_1[i] = vertice1[i] / vertice1[3] - vertice2[i] / vertice2[3];
    vector0_c[i] = (vertice1[i] / vertice1[3] + vertice2[i] / vertice2[3]) / 2;
  }
  // console.log(vector0_c);

  var high = Math.sqrt(
      vector2_1[0] * vector2_1[0] + vector2_1[1] * vector2_1[1] +
      vector2_1[2] * vector2_1[2]);
  // console.log(high);
  // 上下两个圆面的y坐标
  var y1 = high / 2;
  var y2 = (-1) * high / 2;

  //变换矩阵
  var modelMatrix = new Matrix4();
  var a_Z;
  var a_Y;
  if (vector2_1[1] == 0) {
    a_Z = Math.PI / 2;
  } else {
    a_Z = Math.atan(vector2_1[0] / vector2_1[1]);
  }
  var x_y =
      Math.sqrt(vector2_1[0] * vector2_1[0] + vector2_1[1] * vector2_1[1]);
  if (x_y == 0) {
    a_Y = Math.PI / 2;
  } else {
    a_Y = Math.atan(vector2_1[2] / x_y);
  }
  // console.log(180 * a_Z / Math.PI);
  // console.log(180 * a_Y / Math.PI);
  modelMatrix.setTranslate(vector0_c[0], vector0_c[1], vector0_c[2]);
  modelMatrix.rotate(180 * a_Y / Math.PI, 0, 1, 0);
  modelMatrix.rotate(180 * a_Z / Math.PI, 0, 0, 1);

  // console.log(modelMatrix.elements);
  //初始化缓存区
  n = cylinderInitVertexBuffers(gl, y1, y2, r, colors);
  if (n < 0) {
    console.log('Failed to set the vertex information');
    return;
  }

  // gl.clearColor(0.0, 0.0, 0.0, 1.0);
  // gl.enable(gl.DEPTH_TEST);



  var u_ModelMatrix = gl.getUniformLocation(gl.program, 'u_ModelMatrix');
  var u_MvpMatrix = gl.getUniformLocation(gl.program, 'u_MvpMatrix');
  var u_NormalMatrix = gl.getUniformLocation(gl.program, 'u_NormalMatrix');
  var u_LightColor = gl.getUniformLocation(gl.program, 'u_LightColor');
  var u_LightPosition = gl.getUniformLocation(gl.program, 'u_LightPosition');
  var u_AmbientLight = gl.getUniformLocation(gl.program, 'u_AmbientLight');
  if (!u_ModelMatrix || !u_MvpMatrix || !u_NormalMatrix || !u_LightColor ||
      !u_LightPosition || !u_AmbientLight) {
    console.log('Failed to get the storage location');
    return;
  }
  var texture = initTextures(gl);
  if (!texture) {
    console.log('Failed to intialize the texture.');
    return;
  }

  // Bind texture object to texture unit 0
  gl.activeTexture(gl.TEXTURE0);
  gl.bindTexture(gl.TEXTURE_2D, texture);
  // 设置光照颜色 (white)
  gl.uniform3f(u_LightColor, 1.0, 1.0, 1.0);
  // 光位置 (in the world coordinate)
  gl.uniform3f(u_LightPosition, 2.3, 4.0, 3.5);
  // 环境光
  gl.uniform3f(u_AmbientLight, 0.2, 0.2, 0.2);


  var mvpMatrix = new Matrix4();
  var normalMatrix = new Matrix4();

  mvpMatrix.setPerspective(30, 1, 1, 100);
  mvpMatrix.lookAt(6, 6, 14, 0, 0, 0, 0, 1, 0);

  mvpMatrix.multiply(modelMatrix);

  normalMatrix.setInverseOf(modelMatrix);
  normalMatrix.transpose();

  gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);

  gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMatrix.elements);

  gl.uniformMatrix4fv(u_NormalMatrix, false, normalMatrix.elements);
  // gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_SHORT, 0);
}

function initTextures(gl, program) {
  var texture = gl.createTexture();  // Create a texture object
  if (!texture) {
    console.log('Failed to create the texture object');
    return null;
  }

  var image = new Image();  // Create a image object
  if (!image) {
    console.log('Failed to create the image object');
    return null;
  }
  // Register the event handler to be called when image loading is completed
  image.onload = function() {
    // Write the image data to texture object
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);  // Flip the image Y coordinate
    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);

    var u_Sampler = gl.getUniformLocation(gl.program, 'u_Sampler');

    gl.uniform1i(u_Sampler, 0);

    gl.bindTexture(gl.TEXTURE_2D, null);  // Unbind texture
  };

  // Tell the browser to load an Image
  image.src = '../img/images.jpg';

  return texture;
}
function updateCylinder(vertice1, vertice2, gl) {
  //圆柱的上下两点的向量
  var vector2_1 = new Array(3);
  //从原点到圆柱中心的向量 = 上下圆心的中点坐标
  var vector0_c = new Array(3);

  for (var i = 0; i < vector2_1.length; i++) {
    vector2_1[i] = vertice1[i] / vertice1[3] - vertice2[i] / vertice2[3];
    vector0_c[i] = (vertice1[i] / vertice1[3] + vertice2[i] / vertice2[3]) / 2;
  }
  // console.log(vector0_c);

  var high = Math.sqrt(
      vector2_1[0] * vector2_1[0] + vector2_1[1] * vector2_1[1] +
      vector2_1[2] * vector2_1[2]);
  // console.log(high);
  // 上下两个圆面的y坐标
  var y1 = high / 2;
  var y2 = (-1) * high / 2;

  //变换矩阵
  var modelMatrix = new Matrix4();
  var a_Z;
  var a_Y;
  if (vector2_1[1] == 0) {
    a_Z = Math.PI / 2;
  } else {
    a_Z = Math.atan(vector2_1[0] / vector2_1[1]);
  }
  var x_y =
      Math.sqrt(vector2_1[0] * vector2_1[0] + vector2_1[1] * vector2_1[1]);
  if (x_y == 0) {
    a_Y = Math.PI / 2;
  } else {
    a_Y = Math.atan(vector2_1[2] / x_y);
  }
  // console.log(180 * a_Z / Math.PI);
  // console.log(180 * a_Y / Math.PI);
  modelMatrix.setTranslate(vector0_c[0], vector0_c[1], vector0_c[2]);
  modelMatrix.rotate(180 * a_Y / Math.PI, 0, 1, 0);
  modelMatrix.rotate(180 * a_Z / Math.PI, 0, 0, 1);

  var u_ModelMatrix = gl.getUniformLocation(gl.program, 'u_ModelMatrix');
  var u_MvpMatrix = gl.getUniformLocation(gl.program, 'u_MvpMatrix');
  var u_NormalMatrix = gl.getUniformLocation(gl.program, 'u_NormalMatrix');
  if (!u_ModelMatrix || !u_MvpMatrix || !u_NormalMatrix) {
    console.log('Failed to get the storage location');
    return;
  }

  var mvpMatrix = new Matrix4();
  var normalMatrix = new Matrix4();

  mvpMatrix.setPerspective(30, 1, 1, 100);
  mvpMatrix.lookAt(6, 6, 14, 0, 0, 0, 0, 1, 0);

  mvpMatrix.multiply(modelMatrix);

  normalMatrix.setInverseOf(modelMatrix);
  normalMatrix.transpose();

  gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);

  gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMatrix.elements);

  gl.uniformMatrix4fv(u_NormalMatrix, false, normalMatrix.elements);
  // gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_SHORT, 0);
}

function cylinderInitVertexBuffers(gl, y1, y2, r, color) {
  var num = 120;                              //一个园面的扇形数
  var vertice_num = ((num + 1) * 3 + 1) * 2;  //点数量
  //点位置
  var vertices = new Float32Array(vertice_num * 3);
  //点颜色
  var colors = new Float32Array(vertice_num * 3);
  //法向量
  var normals = new Float32Array(vertice_num * 3);
  //点索引
  var indices = new Uint16Array(num * 4 * 3);


  //计算圆上的点
  //上下两个圆面的圆心
  var index = 0;
  var tmpVertice = new Array();
  var tmpNormal1 = new Array();
  var tmpNormal2 = new Array();
  tmpVertice[0] = 0;
  tmpVertice[1] = y1;
  tmpVertice[2] = 0;
  vertices.set(tmpVertice, index);
  colors.set(color, index);
  normals.set([0, 1, 0], index);
  index += 3;

  tmpVertice[1] = y2;
  vertices.set(tmpVertice, index);
  colors.set(color, index);
  normals.set([0, -1, 0], index);
  index += 3;

  //圆上的点
  var aa = 0;
  var a = (1 / num) * Math.PI;
  tmpNormal1[1] = 0;
  tmpNormal2[1] = 0;
  for (var i = 0; i < num + 1; i++) {
    aa = (i / num) * 2 * Math.PI;
    tmpNormal1[0] = Math.cos(aa - a);
    tmpNormal1[2] = Math.sin(aa - a);
    tmpNormal2[0] = Math.cos(aa + a);
    tmpNormal2[2] = Math.sin(aa + a);

    tmpVertice[0] = r * Math.cos(aa);
    tmpVertice[1] = y1;
    tmpVertice[2] = r * Math.sin(aa);


    vertices.set(tmpVertice, index);
    colors.set(color, index);
    normals.set(tmpNormal1, index);
    index += 3;
    vertices.set(tmpVertice, index);
    colors.set(color, index);
    normals.set([0, 1, 0], index);
    index += 3;
    vertices.set(tmpVertice, index);
    colors.set(color, index);
    normals.set(tmpNormal2, index);
    index += 3;

    tmpVertice[1] = y2;
    vertices.set(tmpVertice, index);
    colors.set(color, index);
    normals.set(tmpNormal1, index);
    index += 3;
    vertices.set(tmpVertice, index);
    colors.set(color, index);
    normals.set([0, -1, 0], index);
    index += 3;
    vertices.set(tmpVertice, index);
    colors.set(color, index);
    normals.set(tmpNormal2, index);
    index += 3;
  }

  //计算三角形的组合
  var index = 0;
  var tIndices = new Array(3);

  for (var i = 3; i < vertice_num - 6; i += 6) {
    tIndices[0] = 0;
    tIndices[1] = i;
    tIndices[2] = i + 6;
    indices.set(tIndices, index);
    index += 3;

    tIndices[0] = i + 1;
    tIndices[1] = i + 4;
    tIndices[2] = i + 5;
    indices.set(tIndices, index);
    index += 3;

    tIndices[0] = i + 4;
    tIndices[1] = i + 5;
    tIndices[2] = i + 8;
    indices.set(tIndices, index);
    index += 3;

    tIndices[0] = 1;
    tIndices[1] = i + 3;
    tIndices[2] = i + 9;
    indices.set(tIndices, index);
    index += 3;
  }



  var high = y2 - y1;
  var tmpColorOrTex = 1.0;
  //颜色或纹理判断值
  var colorOrTexs = [];
  //纹理图片坐标
  var texCoords = new Float32Array(vertice_num * 2);
  var texH, texL;
  if (high > (2 * Math.PI * r)) {
    texH = 1;
    texL = (2 * Math.PI * r) / high;
  } else {
    texH = high / (2 * Math.PI * r);
    texL = 1;
  }
  console.log(texH);

  console.log(texL);
  var tmpTexCoord = new Array();
  var tex_index = 0;
  tmpTexCoord[0] = 0;
  tmpTexCoord[1] = 0;
  texCoords.set(tmpTexCoord, tex_index);
  colorOrTexs.push(0);
  tex_index += 2;
  texCoords.set(tmpTexCoord, tex_index);
  colorOrTexs.push(0);
  tex_index += 2;
  for (var i = 0; i < num + 1; i++) {
    tmpTexCoord[0] = i * texL / (num + 1);
    tmpTexCoord[1] = texH;
    texCoords.set(tmpTexCoord, tex_index);
    colorOrTexs.push(tmpColorOrTex);
    tex_index += 2;
    texCoords.set(tmpTexCoord, tex_index);
    colorOrTexs.push(0);
    tex_index += 2;
    texCoords.set(tmpTexCoord, tex_index);
    colorOrTexs.push(tmpColorOrTex);
    tex_index += 2;

    tmpTexCoord[1] = 0;
    texCoords.set(tmpTexCoord, tex_index);
    colorOrTexs.push(tmpColorOrTex);
    tex_index += 2;
    texCoords.set(tmpTexCoord, tex_index);
    colorOrTexs.push(0);
    tex_index += 2;
    texCoords.set(tmpTexCoord, tex_index);
    colorOrTexs.push(tmpColorOrTex);
    tex_index += 2;
  }

  if (!initArrayBuffer(gl, 'a_TexCoord', texCoords, 2)) return -1;
  if (!initArrayBuffer(gl, 'a_Position', vertices, 3)) return -1;
  if (!initArrayBuffer(gl, 'a_Color', colors, 3)) return -1;
  if (!initArrayBuffer(gl, 'a_Normal', normals, 3)) return -1;
  if (!initArrayBuffer(gl, 'a_ColorOrTex', new Float32Array(colorOrTexs), 1))
    return -1;
  // Unbind the buffer object
  gl.bindBuffer(gl.ARRAY_BUFFER, null);

  // Write the indices to the buffer object
  var indexBuffer = gl.createBuffer();
  if (!indexBuffer) {
    console.log('Failed to create the buffer object');
    return false;
  }
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);

  console.log(indices.length);
  return indices.length;
}


function initArrayBuffer(gl, attribute, data, num) {
  console.log(attribute);
  // Create a buffer object
  var buffer = gl.createBuffer();
  if (!buffer) {
    console.log('Failed to create the buffer object');
    return false;
  }
  // Write date into the buffer object
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
  // Assign the buffer object to the attribute variable
  var a_attribute = gl.getAttribLocation(gl.program, attribute);
  if (a_attribute < 0) {
    console.log('Failed to get the storage location of ' + attribute);
    return false;
  }
  gl.vertexAttribPointer(a_attribute, num, gl.FLOAT, false, 0, 0);
  // Enable the assignment of the buffer object to the attribute variable
  gl.enableVertexAttribArray(a_attribute);

  return true;
}